
import * as obvm from '../runtime/vm.mjs';
class ProxyFSM {
    constructor(server, scene, vmid, fsmid) {
        this.server = server;
        this.scene = scene;
        this.vmid = vmid;
        this.fsmid = fsmid;
    }
    PostMessage(msg, st, uf, local) {
        let msgArrayBuffer = st.fsm.VM.messageToBuffer(msg, st, uf, local);
        _sendToServer.call(this.server, this.scene, msgArrayBuffer, st.fsm, { vmid: this.vmid, fsmid: this.fsmid });
    }
    toString(){
        return `ProxyFSM(${this.scene},${this.vmid},${this.fsmid})`;
    }
}
/**
 * 向服务器门户发送请求
 *
 * @param target {String} 目标地址
 * @param msgArrayBuffer {Uint8Array}  数据
 * @param fsm {obvm.OBFSM} 有限状态机
 * @returns 无返回值
 */
function _sendToServer(target, msgArrayBuffer, fsm, targetFSM) {
    let vm = fsm.VM;
    const blob = new Blob([msgArrayBuffer], { type: 'application/octet-stream' });
    let headers = {
        'Content-Type': 'application/octet-stream',
        'callerfsmid': fsm.id,
        'callervmid': fsm.VM.id,
    };
    if (targetFSM) {
        headers.targetfsmid = targetFSM.fsmid;
        headers.targetvmid = targetFSM.vmid;
    }
    fetch(`${this.server}/${target}/msg`, {
        method: 'POST',
        headers,
        body: blob // 将数据转换为 JSON 字符串
    }).then(async (response) => {
        if (response.ok) {
            let headers = response.headers;
            let vmid = headers.get('Targetvmid');
            let fsmid = headers.get('Targetfsmid');
            if (vmid) {
                let targetVM = fsm.VM;
                if (vmid != targetVM.id) {
                    console.error('targetVM wrong', vmid, targetVM.id);
                    return;
                }
                if (targetVM === vm) {
                    let targetFSM = targetVM.getFsmByID(fsmid);
                    if (targetFSM === fsm) {
                        let uint8arr = new Uint8Array(await response.arrayBuffer());
                        let proxy = new ProxyFSM(this, target, headers.get('callervmid'), headers.get('callerfsmid'));
                        let msg = vm.u8arrayToMessage(uint8arr, () => proxy);
                        msg.__csnetwork__ = true;
                        fsm.PostMessage(msg);
                        if (this.receiveCallback) {
                            this.receiveCallback(msg, vm, fsm);
                        }
                    } else {
                        console.error('targetFSM wrong', fsmid, targetFSM.id);
                    }
                }
            } else {
                console.error('targetVM or targetFSM is null', vmid, fsmid);
            }


        } else {
            response.text().then(text => {
                console.error(text, response);
                let log = `${text} (${response.status} ${response.statusText})`;
                fsm.PostMessage(new obvm.EventMessage("ServiceError", 'String', log, null));
            });
        }
    }).catch(e => {
        console.error(e);
        fsm.PostMessage(new obvm.EventMessage("NetworkError", 'String', e.message, null));
    });
}
function sendMessageToServer(builder, args) {
    let that = this;
    let targetIdx = args[1];
    targetIdx = targetIdx & 0xFFF;
    let targetF = builder.StringRegister(targetIdx);

    let titleIdx = args[2];
    titleIdx = titleIdx & 0xFFF;
    let titleF = builder.StringRegister(titleIdx);

    let dataIdx = args[3];
    let dataRegType = (dataIdx & 0xF000) >> 12;
    dataIdx = dataIdx & 0xFFF;
    let dataF;
    switch (dataRegType) {
        case 0:
            dataF = builder.LongRegister(dataIdx);
            break;
        case 1:
            dataF = builder.DoubleRegister(dataIdx);
            break;
        case 2:
            dataF = builder.StringRegister(dataIdx);
            break;
        case 3:
            dataF = builder.StructRegister(dataIdx);
            break;
        case 4:
            dataF = builder.NObjectRegister(dataIdx);
            break;
    }
    builder.PushAction((st, f, local, pos) => {
        let vm = st.fsm.VM;
        let target = targetF(st, f, local);
        let title = titleF(st, f, local);
        let data = dataF(st, f, local);
        let dataType = obvm.Message.ArgTypeOf(dataRegType, data);
        let msg = new obvm.UserMessage(title, dataType, data, st.fsm);
        let msgBuffer = vm.messageToBuffer(msg, st, f, local);
        _sendToServer.call(this, target, msgBuffer, st.fsm);
        return pos + 1;
    });
}
function isNetworkMessage(state, roarfunction, localvar) {
    return !!(state?.currentMessage?.__csnetwork__);
}
class CSNetworkClient {
    server = 'http://127.0.0.1:3001/roar_server';
    receiveCallback;
    install(script) {
        script.InstallLib("CSNetwork-Client", "CSNetwork-Client", [
            sendMessageToServer.bind(this),
            script.NativeUtil.closureReturnValue(isNetworkMessage, 'LongRegister', [], true),
        ]);
    }
}
export default CSNetworkClient;